﻿using System;
using System.Collections.Generic;
using System.Linq;
using ExcelReader.Helper;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ExcelReader
{
    public class Reader : IReader, IDisposable
    {
        private readonly FileStream _fileStream;

        public Reader(FileStream fileStream)
        {
            if (fileStream == null)
                throw new IOException("Missing Excel File Stream.");
            _fileStream = fileStream;
        }

        public List<object> GetWorksheet(object obj, string worksheetName, int startRow, int endRow)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");

            if (string.IsNullOrEmpty(worksheetName))
                throw new ArgumentNullException("worksheetName");

            var result = new List<object>(); 
            
            var spreadsheetDocument = SpreadsheetDocument.Open(_fileStream, false);

            var workbookPart = spreadsheetDocument.WorkbookPart;
            IEnumerable<Sheet> sheets = workbookPart.Workbook.Descendants<Sheet>();

            var dataSheet = sheets.Single(p => p.Name.Value.Equals(worksheetName));
            var dataSheetPart = (WorksheetPart)workbookPart.GetPartById(dataSheet.Id);

            var mergeCellInformation = ExcelHelper.MergeCellInformation(dataSheetPart);

            foreach (var row in dataSheetPart.Worksheet.Descendants<Row>().Skip(startRow - 1).Where(row => row != null))
            {
                var temp = Activator.CreateInstance(obj.GetType());

                foreach (var propertyInfo in obj.GetType().GetProperties())
                {
                    var columnName = ColumnMapperHelper.GetColumnNameInExcel(obj.GetType(), propertyInfo.Name);
                    var excelCoordinate = string.Format("{0}{1}", columnName, row.RowIndex);
                    excelCoordinate = ExcelHelper.OverideExcelCoordinate(mergeCellInformation, excelCoordinate);
                    var valueInString = ExcelHelper.GetCellValue(excelCoordinate, workbookPart, dataSheetPart);
                    var value = ConverterHelper.Convert(valueInString, propertyInfo.PropertyType);
                    propertyInfo.SetValue(temp, value, null);
                }
                result.Add(temp);

                if (endRow != 0) //if user specify 0, then we take all
                {
                    if (endRow == row.RowIndex)
                    {
                        break;
                    }
                }
            }

            return result;
        }

        public List<object> GetWorksheet(object obj, string worksheetName)
        {
            return GetWorksheet(obj, worksheetName, 0, 0);
        }

        public void Dispose()
        {
            _fileStream.Dispose();
        }
    }
}
